package edu.ivanov.apm.ui;

import edu.ivanov.apm.quant.Solution;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

/**
 * User: Илья
 * Date: 06.10.13
 * Time: 11:00
 */
public class GraphScene extends Scene {

	private static final String FORM_TITLE = "Уравнение Шрёдингера";

	private static final int WIDTH = 600;
	private static final int HEIGHT = 600;

	private static final String CHART_TITLE = "Волновая функция %d-го состояния\nЗначение энергии: %f\nСреднее значение энергии: %f";
	private static final String FORWARD_SERIES_NAME = "Интегрирование вперёд";
	private static final String BACKWARD_SERIES_NAME = "Интегрирование назад";
	private static final String TAB_TITLE = "Состояние %d";

	private AnchorPane root;
	private TabPane tabs;

	private GraphScene() {
		super(new AnchorPane(), WIDTH, HEIGHT);
		root = (AnchorPane) getRoot();

		tabs = new TabPane();
		root.getChildren().add(tabs);
		setAnchor(tabs, 10.0);
	}

	private void draw(Solution[] solutions) {
		for (int i = 0; i < solutions.length; i++) {
			Solution solution = solutions[i];
			if (solution == null)
				continue;

			LineChart<Number, Number> chart = new LineChart<Number, Number>(new NumberAxis(), new NumberAxis());
			chart.setTitle(String.format(CHART_TITLE, i, solution.getE(), solution.getMean()));

			addSeries(chart, solution.getForward(), solution.getL(), FORWARD_SERIES_NAME);
			addSeries(chart, solution.getBackward(), solution.getL(), BACKWARD_SERIES_NAME);

			AnchorPane anchor = new AnchorPane();
			anchor.getChildren().add(chart);
			setAnchor(chart, 10.0);

			Tab tab = new Tab();
			tab.setContent(anchor);
			tab.setClosable(false);
			tab.setText(String.format(TAB_TITLE, i));

			tabs.getTabs().add(tab);
		}
	}

	private void addSeries(LineChart<Number, Number> chart, double[] y, double l, String title) {
		if (y == null || y.length < 2)
			return;

		XYChart.Series<Number, Number> series = new XYChart.Series<Number, Number>();
		series.setName(title);

		double h = 2 * l / (y.length - 1);
		for (int i = 0; i < y.length; i++) {
			double xi = - l + i * h;
			series.getData().add(new XYChart.Data<Number, Number>(xi, y[i]));
		}

		chart.getData().add(series);
	}

	private static void setAnchor(Node node, double padding) {
		AnchorPane.setTopAnchor(node, padding);
		AnchorPane.setRightAnchor(node, padding);
		AnchorPane.setBottomAnchor(node, padding);
		AnchorPane.setLeftAnchor(node, padding);
	}

	/**
	 * Показывает форму с графиком решения.
	 *
	 * @param solutions Решение уравнения.
	 */
	public static void show(Solution[] solutions) {
		if (solutions == null)
			return;

		UIApplication.setSolutions(solutions);
		Application.launch(UIApplication.class, (String[]) null);
	}

	public static class UIApplication extends Application {

		public void start(Stage stage) throws Exception {
			GraphScene graph = new GraphScene();
			stage.setScene(graph);
			stage.setTitle(FORM_TITLE);
			stage.show();

			graph.draw(solutions);
		}

		private static Solution[] solutions;

		public static void setSolutions(Solution[] solutions) {
			UIApplication.solutions = solutions;
		}
	}
}
